﻿using System;
using System.Collections.Generic;
using System.Text;
using RoverStudio.Common.PositionSource;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.Diagnostics;

namespace WebcamDShow
{
    class AForgeVideoSource : IVideoSourceCommon
    {
        private IVideoSource videoSource = null;
        private Camera camera;

        public IVideoSource VideoSource
        {
            get { return videoSource; }
        }

        public AForgeVideoSource(string name)
        {
            this.name = name;
        }

        public void SetWebcamSource(string deviceMoniker)
        {
            videoSource = new VideoCaptureDevice(deviceMoniker);
        }

        public void SetFileSource(string filePath)
        {
            videoSource = new FileVideoSource(filePath);
        }

        private int desiredWidth = 640;

        public int DesiredWidth
        {
            get { return desiredWidth; }
            set { desiredWidth = value; }
        }

        private int desiredHeight = 480;

        public int DesiredHeight
        {
            get { return desiredHeight; }
            set { desiredHeight = value; }
        }

        private int desiredFrameRate = 15;

        public int DesiredFrameRate
        {
            get { return desiredFrameRate; }
            set { desiredFrameRate = value; }
        }


        // Open video source
        public void OpenVideoSource()
        {
            if (videoSource == null)
                return;

            // close previous video source
            CloseVideoSource();

            // create camera
            camera = new Camera(videoSource);

            camera.DesiredFrameSize = new Size(DesiredWidth, DesiredHeight);
            camera.DesiredFrameRate = DesiredFrameRate;

            camera.NewFrame += new EventHandler(camera_NewFrame);
            // start camera
            camera.Start();
        }

        public void CloseVideoSource()
        {
            lock (this)
            {
                if (camera != null)
                {
                    camera.NewFrame -= new EventHandler(camera_NewFrame);
                    Application.DoEvents();
                    if (camera != null)
                    {
                        // signal camera to stop
                        camera.SignalToStop();
                        // wait 2 seconds until camera stops
                        for (int i = 0; (i < 20) && (camera.IsRunning); i++)
                        {
                            Thread.Sleep(100);
                        }
                        if (camera.IsRunning)
                        {
                            camera.Stop();
                        }
                        camera = null;
                    }
                }
            }
        }


        // On new frame
        private void camera_NewFrame(object sender, EventArgs e)
        {
            Debug.Assert(camera == sender, "camera != sender", "Something wrong with the camera events");
            if (NewFrame != null)
                NewFrame(((Camera)sender).LastFrame);
        }

        #region IVideoSourceCommon Members
        private string name;

        public string Name
        {
            get { return name; }
        }

        public bool IsActive
        {
            get { throw new NotImplementedException(); }
        }

        public event NewFrameDelegate NewFrame;

        #endregion
    }
}
